import './index.css'
import '../css/animate.min.css'
import './canvas'
import { addQipao, showTitle } from './prizeList'
import { NUMBER_MATRIX } from './config.js'

const setLocalLeftUsers = (leftUsers) => {
  localStorage.setItem('leftUsers', JSON.stringify(leftUsers))
}

const getLocalLeftUsers = (leftUsers) => {
  return JSON.parse(localStorage.getItem('leftUsers'))
}

const getLocalLuckCount = () => {
  const count = localStorage.getItem('luckyCount')
  if (count) return Number(count)
  return 0
}

const setLocalLuckCount = (addCount) => {
  localStorage.setItem('luckyCount', getLocalLuckCount() + addCount)
}

let imgUrl ='https://i02piccdn.sogoucdn.com/6f16cd6360b16405'

let btns = {
  enter: document.querySelector('#enter'),
  lotteryBar: document.querySelector('#lotteryBar'),
  lottery: document.querySelector('#lottery'),
}

let users = [] // 参与抽奖人员
let leftUsers // 剩余未中奖人员
const eachCount = 2 // 每次中将个数

let ROW_COUNT = 7
let COLUMN_COUNT = 17
const TOTAL_CARDS = ROW_COUNT * COLUMN_COUNT
let HIGHLIGHT_CELL = []
let selectedCardIndex = []
let currentLuckys = []
let isLotting = false
const ROTATE_TIME = 3000
const ROTATE_LOOP = 1000
let rotate = false
let rotateObj

let camera,
  scene,
  renderer,
  controls,
  threeDCards = [],
  targets = {
    table: [],
    sphere: [],
  }
let Resolution = 1 // 当前的比例

initAll()

/**
 * 初始化所有DOM
 */
function initAll() {
  window.AJAX({
    url: '/getUsers?workspace=sjz',
    success(data) {
      HIGHLIGHT_CELL = createHighlight()
      users = data
      leftUsers = getLocalLeftUsers() || [...data]
      initCards()
      animate()
      shineCard()
      showTitle('北纬路', getLocalLuckCount())
    },
  })
}

function initCards() {
  let member = users.slice(),
    length = member.length

  let isBold = false,
    showTable = leftUsers.length === users.length,
    index = 0,
    position = {
      x: (140 * COLUMN_COUNT - 20) / 2,
      y: (180 * ROW_COUNT - 20) / 2,
    }

  camera = new THREE.PerspectiveCamera(
    40,
    window.innerWidth / window.innerHeight,
    1,
    10000,
  )
  camera.position.z = 3000

  scene = new THREE.Scene()

  for (let i = 0; i < ROW_COUNT; i++) {
    for (let j = 0; j < COLUMN_COUNT; j++) {
      isBold = HIGHLIGHT_CELL.includes(j + '-' + i)
      var element = createCard(member[index % length], isBold, index, showTable)

      var object = new THREE.CSS3DObject(element)
      object.position.x = Math.random() * 4000 - 2000
      object.position.y = Math.random() * 4000 - 2000
      object.position.z = Math.random() * 4000 - 2000
      scene.add(object)
      threeDCards.push(object)

      var object = new THREE.Object3D()
      object.position.x = j * 140 - position.x
      object.position.y = -(i * 180) + position.y
      targets.table.push(object)
      index++
    }
  }

  // sphere

  var vector = new THREE.Vector3()

  for (var i = 0, l = threeDCards.length; i < l; i++) {
    var phi = Math.acos(-1 + (2 * i) / l)
    var theta = Math.sqrt(l * Math.PI) * phi
    var object = new THREE.Object3D()
    object.position.setFromSphericalCoords(800 * Resolution, phi, theta)
    vector.copy(object.position).multiplyScalar(2)
    object.lookAt(vector)
    targets.sphere.push(object)
  }

  renderer = new THREE.CSS3DRenderer()
  renderer.setSize(window.innerWidth, window.innerHeight)
  document.getElementById('container').appendChild(renderer.domElement)

  controls = new THREE.TrackballControls(camera, renderer.domElement)
  controls.rotateSpeed = 0.5
  controls.minDistance = 500
  controls.maxDistance = 6000
  controls.addEventListener('change', render)

  bindEvent()

  if (showTable) {
    switchScreen('enter')
  } else {
    switchScreen('lottery')
  }
}

function setLotteryStatus(status = false) {
  isLotting = status
}

/**
 * 事件绑定
 */
function bindEvent() {
  document.querySelector('#menu').addEventListener('click', function (e) {
    e.stopPropagation()
    // 如果正在抽奖，则禁止一切操作
    if (isLotting) {
      if (e.target.id === 'lottery') {
        rotateObj.stop()
        btns.lottery.innerHTML = '开始抽奖'
      } else {
        addQipao('正在抽奖，抽慢一点点～～')
      }
      return false
    }

    let target = e.target.id
    switch (target) {
      // 进入抽奖
      case 'enter':
        removeHighlight()
        addQipao(`马上抽取奖项,不要走开。`)
        rotate = true
        switchScreen('lottery')
        break
      // 重置
      case 'reset':
        let doREset = window.confirm(
          '是否确认重置数据，重置后，当前已抽的奖项全部清空？',
        )
        if (!doREset) {
          return
        }
        addQipao('重置所有数据，重新抽奖')
        addHighlight()
        resetCard()
        // 重置所有数据
        currentLuckys = []
        leftUsers = Object.assign([], users)
        setLocalLeftUsers(leftUsers)
        switchScreen('enter')
        break
      // 抽奖
      case 'lottery':
        setLotteryStatus(true)
        resetCard().then((res) => {
          // 抽奖
          lottery()
        })
        addQipao(`正在抽取奖项, 调整好姿势`)
        break
    }
  })

  window.addEventListener('resize', onWindowResize, false)
}

function switchScreen(type) {
  switch (type) {
    case 'enter':
      btns.enter.classList.remove('none')
      btns.lotteryBar.classList.add('none')
      transform(targets.table, 2000)
      break
    default:
      btns.enter.classList.add('none')
      btns.lotteryBar.classList.remove('none')
      transform(targets.sphere, 2000)
      break
  }
}

/**
 * 创建元素
 */
function createElement(css, text) {
  let dom = document.createElement('div')
  dom.className = css || ''
  dom.innerHTML = text || ''
  return dom
}

/**
 * 创建名牌
 */
function createCard(user, isBold, id, showTable) {
  var element = createElement()
  element.id = 'card-' + id

  if (isBold) {
    element.className = 'element lightitem'
    if (showTable) {
      element.classList.add('highlight')
    }
  } else {
    element.className = 'element'
    element.style.backgroundColor =
      'rgba(0,127,127,' + (Math.random() * 0.7 + 0.25) + ')'
  }
  return element
}

function removeHighlight() {
  document.querySelectorAll('.highlight').forEach((node) => {
    node.classList.remove('highlight')
  })
}

function addHighlight() {
  document.querySelectorAll('.lightitem').forEach((node) => {
    node.classList.add('highlight')
  })
}

/**
 * 渲染地球等
 */
function transform(targets, duration) {
  // TWEEN.removeAll();
  for (var i = 0; i < threeDCards.length; i++) {
    var object = threeDCards[i]
    var target = targets[i]

    new TWEEN.Tween(object.position)
      .to(
        {
          x: target.position.x,
          y: target.position.y,
          z: target.position.z,
        },
        Math.random() * duration + duration,
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start()

    new TWEEN.Tween(object.rotation)
      .to(
        {
          x: target.rotation.x,
          y: target.rotation.y,
          z: target.rotation.z,
        },
        Math.random() * duration + duration,
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start()
  }

  new TWEEN.Tween(this)
    .to({}, duration * 2)
    .onUpdate(render)
    .start()
}

function rotateBall() {
  return new Promise((resolve, reject) => {
    scene.rotation.y = 0
    rotateObj = new TWEEN.Tween(scene.rotation)
    rotateObj
      .to(
        {
          y: Math.PI * 6 * ROTATE_LOOP,
        },
        ROTATE_TIME * ROTATE_LOOP,
      )
      .onUpdate(render)
      .start()
      .onStop(() => {
        scene.rotation.y = 0
        resolve()
      })
      .onComplete(() => {
        resolve()
      })
  })
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
  render()
}

function animate() {
  requestAnimationFrame(animate)
  TWEEN.update()
  controls.update()
}

function render() {
  renderer.render(scene, camera)
}

function selectCard(duration = 600) {
  rotate = false
  let width = 140,
    tag = -(currentLuckys.length - 1) / 2,
    locates = []

  // 计算位置信息, 大于5个分两排显示
  if (currentLuckys.length > 5) {
    let yPosition = [-87, 87],
      l = selectedCardIndex.length,
      mid = Math.ceil(l / 2)
    tag = -(mid - 1) / 2
    for (let i = 0; i < mid; i++) {
      locates.push({
        x: tag * width * Resolution,
        y: yPosition[0] * Resolution,
      })
      tag++
    }

    tag = -(l - mid - 1) / 2
    for (let i = mid; i < l; i++) {
      locates.push({
        x: tag * width * Resolution,
        y: yPosition[1] * Resolution,
      })
      tag++
    }
  } else {
    for (let i = selectedCardIndex.length; i > 0; i--) {
      locates.push({
        x: tag * width * Resolution,
        y: 0 * Resolution,
      })
      tag++
    }
  }

  selectedCardIndex.forEach((cardIndex, index) => {
    changeCard(cardIndex, currentLuckys[index], true)
    var object = threeDCards[cardIndex]
    new TWEEN.Tween(object.position)
      .to(
        {
          x: locates[index].x,
          y: locates[index].y * Resolution,
          z: 2200,
        },
        Math.random() * duration + duration,
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start()

    new TWEEN.Tween(object.rotation)
      .to(
        {
          x: 0,
          y: 0,
          z: 0,
        },
        Math.random() * duration + duration,
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start()

    object.element.classList.add('prize')
    tag++
  })

  new TWEEN.Tween(this)
    .to({}, duration * 2)
    .onUpdate(render)
    .start()
    .onComplete(() => {
      // 动画结束后可以操作
      setLotteryStatus()
    })
}

/**
 * 重置抽奖牌内容
 */
function resetCard(duration = 500) {
  if (currentLuckys.length === 0) {
    return Promise.resolve()
  }

  selectedCardIndex.forEach((index) => {
    let object = threeDCards[index],
      target = targets.sphere[index]

    new TWEEN.Tween(object.position)
      .to(
        {
          x: target.position.x,
          y: target.position.y,
          z: target.position.z,
        },
        Math.random() * duration + duration,
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start()

    new TWEEN.Tween(object.rotation)
      .to(
        {
          x: target.rotation.x,
          y: target.rotation.y,
          z: target.rotation.z,
        },
        Math.random() * duration + duration,
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start()
  })

  return new Promise((resolve, reject) => {
    new TWEEN.Tween(this)
      .to({}, duration * 2)
      .onUpdate(render)
      .start()
      .onComplete(() => {
        selectedCardIndex.forEach((index) => {
          let object = threeDCards[index]
          object.element.classList.remove('prize')
        })
        resolve()
      })
  })
}

/**
 * 抽奖
 */
function lottery() {
  // if (isLotting) {
  //   rotateObj.stop();
  //   btns.lottery.innerHTML = "开始抽奖";
  //   return;
  // }
  btns.lottery.innerHTML = '结束抽奖'
  rotateBall().then(() => {
    // 将之前的记录置空
    currentLuckys = []
    selectedCardIndex = []
    let perCount = eachCount, // 每次抽几个奖
      leftCount = leftUsers.length // 剩余未中奖人员个数
    // 如果剩余未中奖人数小于本次抽奖个数

    if (leftCount < perCount) {
      addQipao('剩余参与抽奖人员不足，现在重新设置所有人员可以进行二次抽奖！')
      leftUsers = users.slice()
      leftCount = leftUsers.length
    }

    const currentLuckysIds = []

    for (let i = 0; i < perCount; i++) {
      let luckyId = random(leftCount)
      let lucks = leftUsers.splice(luckyId, 1)[0]
      currentLuckys.push(lucks)
      currentLuckysIds.push(lucks[0])
      leftCount--

      let cardIndex = random(TOTAL_CARDS)
      while (selectedCardIndex.includes(cardIndex)) {
        cardIndex = random(TOTAL_CARDS)
      }
      selectedCardIndex.push(cardIndex)
    }

    // leftUsers = leftUsers.filter(item => !currentLuckysIds.includes(item[0]))
    setLocalLeftUsers(leftUsers)
    setLocalLuckCount(perCount)
    showTitle('北纬路', getLocalLuckCount())
    selectCard()
  })
}

/**
 * 随机抽奖
 */
function random(num) {
  // Math.floor取到0-num-1之间数字的概率是相等的
  return Math.floor(Math.random() * num)
}

/**
 * 切换名牌人员信息
 */
function changeCard(cardIndex, user, isSelect) {
  if (isSelect) {
    let card = [...threeDCards][cardIndex].element

    card.innerHTML = `<img src=${imgUrl} class="avaterSelect"></img><div class="avaterName">${
      user[1]
    }</div><div class="details">${'这是祝福语~这是祝福语~这是祝福语~这是祝福语~' || ''}</div>`
  } else {
    let card = threeDCards[cardIndex].element
    card.innerHTML = `<img src=${imgUrl} class="avater"></img>`
  }
}

/**
 * 仅初始化切换名牌背景
 */
function shine(cardIndex, color) {
  let card = threeDCards[cardIndex].element
  card.style.backgroundColor =
    color || 'rgba(0,127,127,' + (Math.random() * 0.7 + 0.25) + ')'
}

/**
 * 初始化切换背景和人员信息
 */
function shineCard() {
  let maxCard = 10,
    maxUser
  let shineCard = 10 + random(maxCard)

  setInterval(() => {
    // 正在抽奖停止闪烁
    if (isLotting) {
      return
    }
    maxUser = leftUsers.length
    for (let i = 0; i < shineCard; i++) {
      let index = random(maxUser),
        cardIndex = random(TOTAL_CARDS)
      // 当前显示的已抽中名单不进行随机切换
      if (selectedCardIndex.includes(cardIndex)) {
        continue
      }
      shine(cardIndex)
      changeCard(cardIndex, leftUsers[index])
    }
  }, 500)
}

function createHighlight() {
  let year = new Date().getFullYear() + ''
  let step = 4,
    xoffset = 1,
    yoffset = 1,
    highlight = []

  year.split('').forEach((n) => {
    highlight = highlight.concat(
      NUMBER_MATRIX[n].map((item) => {
        return `${item[0] + xoffset}-${item[1] + yoffset}`
      }),
    )
    xoffset += step
  })

  return highlight
}

let onload = window.onload

window.onload = function () {
  onload && onload()

  let music = document.querySelector('#music')

  let rotated = 0,
    stopAnimate = false,
    musicBox = document.querySelector('#musicBox')

  function animate() {
    requestAnimationFrame(function () {
      if (stopAnimate) {
        return
      }
      rotated = rotated % 360
      musicBox.style.transform = 'rotate(' + rotated + 'deg)'
      rotated += 1
      animate()
    })
  }

  musicBox.addEventListener(
    'click',
    function (e) {
      if (music.paused) {
        music.play().then(
          () => {
            stopAnimate = false
            animate()
          },
          () => {
            addQipao('背景音乐自动播放失败，请手动播放！')
          },
        )
      } else {
        music.pause()
        stopAnimate = true
      }
    },
    false,
  )

  setTimeout(function () {
    musicBox.click()
  }, 1000)
}
